import GameControl from './GameControl';
import OnFire from './OnFire';
import { EventName } from './EventName';
import API from './API';
import { Rect, SpriteFrame } from 'cc';

// 负责头条API
// 官方文档：https://microapp.bytedance.com/docs/zh-CN/mini-app/develop/api/foundation/tt-can-i-use
export default class TTApi {

    // 单例模式
    private static _instance: TTApi = null;
    public static getInstance() {
        if (this._instance == null) {
            this._instance = new TTApi();
        }
        return this._instance;
    }

    videoAd: any = null;
    bannerAd: any = null;
    barTop: number = -1;
    videoStatus: any = null;

    // 切换后台的时间戳
    backstageDate: any = 0;

    // banner广告计数器（隐藏5次后，销毁广告重新拉取）
    bannerCount: number = 0;
    bannerTotal: number = 3;

    m_recordManager = null //录屏对象
    m_startVideoTime = null
    m_isClipVideo = null
    m_stopRecordVideoCallback = null
    m_videoPath = null
    m_openShareVideo = null

    _interstitialAd = null;

    shareState = true;

    m_screenShot = null;

    errHandle = {
        1000: '后端接口调用失败',
        1001: '参数错误',
        1002: '广告单元无效',
        1003: '内部错误',
        1004: '无合适的广告',
        1005: '广告组件审核中',
        1006: '广告组件被驳回',
        1007: '广告组件被封禁',
        1008: '广告单元已关闭',
        2001: '小程序启动一定时间内不允许展示插屏广告',
        2002: '距离小程序插屏广告或者激励视频广告上次播放时间间隔不足，不允许展示插屏广告',
        2003: '当前正在播放激励视频广告或者插屏广告，不允许再次展示插屏广告',
        2004: '该项错误不是开发者的异常情况，或因小程序页面切换导致广告渲染失败',
        2005: '插屏广告实例不允许跨页面调用'
    }

    // banner的ID
    bannerIDIndex: number = 0
    bannerIDList: any = [
        '354186e02i8a046755',
    ]

    interstitialAdID = '44ql10tr6d6m4o5532'
    rewardedVideoID = '1j57c558ff52j2g5n1'

    // 微信初始化
    init() {
        // if (!window.tt) return;

        // 获取当前手机的操作系统
        tt.getSystemInfo({
            success(res) {
                this._versions = res.SDKVersion;
                printLog('头条SDK:', this._TAG + this._versions);
                printLog('移动端：', res.platform + res.appName);

                // Android/iOS
                GameControl.getInstance().setPhoneSystem(res.platform);

                // 应用名
                GameControl.getInstance().setAppName(res.appName);
            }
        })

        // 显示当前页面的转发按钮(被动拉起)
        tt.showShareMenu()
        tt.onShareAppMessage(() => {
            let info = GameControl.getInstance().getShareImgList()[0];
            return {
                title: info.desc,
                imageUrl: info.img_path,
                query: `invitationID=${GameControl.getInstance().getOpenID()}`,
                success() {
                    printLog('分享成功');
                },
                fail(e) {
                    printLog('分享失败', e);
                    OnFire.getInstance().emit(EventName.ADD_MESSAGE, {
                        key: 'TipsMessage',
                        value: { path: 'true', text: '分享失败' }
                    });
                }
            }
        });

        tt.onShow((data) => {
            printLog('小游戏回到了前台');
            OnFire.getInstance().emit(EventName.AUDIO_STATUS, { key: 'bgm' });

            // this._callback = () => {
            //     // 更新用户信息
            //     API.getInstance().userUpdata().then(res => {
            //         if (res.status) {
            //             printLog('提交成功')
            //         } else {
            //             printLog('提交失败', res.data)
            //         }
            //     });
            // }
            // setInterval(this._callback(), 120000);

            // GM.OnFire.emit(Notify.AUDIO_STATUS, { key: 'bgm', status: 'resume' })

            // 判断分享是否成功
            // let closeTime = Date.now()
            // GM.OnFire.emit(Notify.SHARE_STATUS, { time: closeTime })

            // // 判断是否其他小游戏跳转回来的
            // if (GM.GameControl.getOtherGameStatus()) {
            //     printLog('是从其他小游戏回来的')
            //     GM.GameControl.setOtherGameStatus(false)

            //     // 获取到试剂（重战页面上使用到）
            //     GM.OnFire.emit(Notify.DEMO_GET_REAGENT, { key: true })
            // }
        })

        tt.onError((res) => {
            printLog('小游戏异常', res);

        })

        tt.onHide((data) => {
            printLog('小游戏隐藏到后台事件', data);
            // clearInterval(this._callback);
            // GM.OnFire.emit(Notify.AUDIO_STATUS, { key: 'stopall', status: 'stop' })

            // 提交排行榜数据
            // this.setUserCloudStorage('MAXPASS', GM.GameControl.getMaxPass())

            // 更新用户信息
            API.getInstance().userUpdata().then(res => {
                if (res.status) {
                    printLog('提交成功')
                } else {
                    printLog('提交失败', res.data)
                }
            });
        })
    }

    // 主动拉起分享界面
    // 使用格式：Constants.SdkFactory.shareAppMessage().then(res => {if (res.status) {分享成功}})
    shareAppMessage() {
        let info = GameControl.getInstance().getShareImgList()[0]
        return new Promise<any>((resolve, reject) => {
            if (window.tt) {
                tt.shareAppMessage({
                    title: info.desc,
                    imageUrl: info.img_path,
                    query: `invitationID=${GameControl.getInstance().getOpenID()}`,
                    success() {
                        resolve({
                            status: true,
                            msg: '分享成功'
                        })
                    },
                    fail(err) {
                        printLog('主动拉起分享失败', err);
                        OnFire.getInstance().emit(EventName.ADD_MESSAGE, {
                            key: 'TipsMessage',
                            value: { path: 'true', text: '分享失败,请稍后再试' }
                        });
                        resolve({
                            status: false,
                            msg: '分享失败'
                        })
                    }
                })
            } else {
                resolve({
                    status: true,
                    msg: '分享成功'
                });
            }
        })
    }

    // 存储数据到本地
    setStorage(key: string, value: any) {
        tt.setStorageSync(key, value);
    }

    // 读取本地数据
    getStorage(key: string) {
        // let value = tt.getStorageSync(key);
        return tt.getStorageSync(key);
    }

    // 判断本地是否存在对应的数据
    hasOwnProperty(key: string) {
        if (tt.getStorageSync(key) == "") {
            return false
        }
        return true
    }

    // 删除key值的本地缓存数据
    removeStorage(key: string) {
        tt.removeStorage({
            key: 'key',
            success(res) {
            }
        })
    }

    //  获取微信右上角按钮的坐标（按钮锚点：（0， 0.5））
    getRightMenuPos() {
        // 添加到我的小程序手势 位置调整
        if (window.tt) {
            let WXScreen = tt.getSystemInfoSync();
            let wxHeight = WXScreen.screenHeight;
            let wxWidth = WXScreen.screenWidth;

            let posObject = tt.getMenuButtonBoundingClientRect();
            let menuWXPosX = posObject.left;
            let menuWXPosY = wxHeight - posObject.top - posObject.height / 2;

            let cocosHeight = cc.winSize.height;
            let cocosWidth = cc.winSize.width;

            // 世界坐标
            let worldPosX = menuWXPosX * cocosWidth / wxWidth;
            let worldPosY = menuWXPosY * cocosHeight / wxHeight;

            // return new cc.Vec2(worldPosX, worldPosY);
        }
    }

    // 监听网络变化状态
    onNetworkStatusChange() {
        tt.onNetworkStatusChange((res) => {
            printLog('网络变动啦', 'onNetworkStatusChange')
            printLog('当前是否有网络连接', res.isConnected)
            printLog('网络类型', res.networkType)
        })
    }

    // 关闭网络变化状态监听
    offNetworkStatusChange() {
        tt.offNetworkStatusChange(() => {
            printLog("关闭网络变化状态监听")
        })
    }

    // 获取网络状态检测
    getNetworkType() {
        tt.getNetworkType({
            success(res) {
                return {
                    'status': 200,
                    'msg': res.networkType,
                    'client': 'wx'
                }
            },
            fail(res) {
                return {
                    'status': 503,
                    'msg': res,
                    'client': 'wx'
                }
            }
        })
    }

    // 小游戏跳转
    // Constants.SdkFactory.navigateToMiniProgram(appId, path).then(res => {if (res.status) {跳转成功}})
    navigateToMiniProgram(appId, path) {
        return new Promise<any>((resolve, reject) => {
            tt.navigateToMiniProgram({
                appId: appId,
                path: path,
                success: (res) => {
                    printLog('跳转成功')

                    // 跳转成功打点
                    API.getInstance().getAllow(appId);

                    // 从导出游戏跳转到其他小游戏
                    // GameControl.getInstance().setOtherGameStatus(true)
                    resolve(true)
                },
                complete: () => {
                    cc.game.resume();
                },
                fail: (res) => {
                    printLog('跳转失败')
                    resolve(false)
                }
            });
        })
    }

    // banner广告设置位置
    // 开启广告：Constants.SdkFactory.createBannerAd();
    createBannerAd() {
        if (window.tt) {

            if (GameControl.getInstance().getAppName() === 'DOUYIN') {
                return;
            }

            const { windowWidth, windowHeight } = tt.getSystemInfoSync();

            // 创建banner实例
            if (this.bannerAd == null) {
                this.bannerAd = tt.createBannerAd({
                    adUnitId: this.bannerIDList[this.bannerIDIndex],
                    adIntervals: 30,
                });
            }

            // banner显示
            this.bannerAd.onLoad(() => {
                this.bannerAd
                    .show()
                    .then(() => {
                        console.log("广告显示成功");
                    })
                    .catch(err => {
                        console.log("广告组件出现问题", err);
                    });
            });

            this.bannerAd.onResize(size => {
                this.bannerAd.style.top = windowHeight - size.height;
                this.bannerAd.style.left = (windowWidth - size.width) / 2;
            });

            this.bannerAd.onError(err => {

                if (err.errCode == 1004) {
                    this.bannerIDIndex == (this.bannerIDList.length - 1) ? this.bannerIDIndex = 0 : this.bannerIDIndex += 1;
                }
            });
        }
    }

    // 隐藏广告：Constants.WXAPI.hideBarAd();
    hideBarAd() {
        if (window.tt) {
            this.destroyBarAd();
            // if (this.bannerAd != null) {
            //     this.bannerCount += 1
            //     if (this.bannerCount == this.bannerTotal) {
            //         this.destroyBarAd()
            //         return
            //     }
            //     printLog('banner广告隐藏')
            //     this.bannerAd.hide()
            // }
        }
    }

    // 销毁广告：Constants.SdkFactory.destroyBarAd();
    destroyBarAd() {
        if (window.tt) {
            if (this.bannerAd != null) {
                printLog('banner广告销毁')
                this.bannerAd.destroy()
                this.bannerAd = null
                this.bannerCount = 0
            }
        }
    }

    // 初始化视频广告
    // 注意：视频组件在开发者工具上无法使用！！！！
    initVideoAd() {
        const phoneSystem = tt.getSystemInfoSync().platform == "devtools";
        if (!window.tt || phoneSystem) return;

        if (this.videoAd == null) {
            this.videoAd = tt.createRewardedVideoAd({
                adUnitId: this.rewardedVideoID
            })

            // 视频加载完成
            this.videoAd.onLoad(() => {
                printLog('激励视频 广告加载成功');
            })

            // 捕获视频流异常事件
            this.videoAd.onError(err => {
                printLog('视频流异常::', this.errHandle[err.errCode]);
                OnFire.getInstance().emit(EventName.ADD_MESSAGE, {
                    key: 'TipsMessage',
                    value: { path: 'true', text: '无适合的视频广告' }
                });
            });

            // 捕获视频关闭事件
            this.videoAd.onClose(res => {
                if (res.isEnded) {
                    // 正常播放结束，可以下发游戏奖励
                    printLog('正常关闭视频广告')
                    OnFire.getInstance().emit(EventName.PLAY_VIDEO_STATUS, { key: true });
                }
                else {
                    // 播放中途退出，不下发游戏奖励
                    printLog('还没有看完视频，关闭不正常')
                    OnFire.getInstance().emit(EventName.PLAY_VIDEO_STATUS, { key: false });
                }
            });
        };
    }

    // 视频广告播放开关
    // 使用：
    // Constants.SdkFactory.playVideoAd().then(res => {if (res.status) {播放成功}})
    playVideoAd() {
        return new Promise<any>((resolve, reject) => {
            if (tt.getSystemInfoSync().platform == 'devtools') {
                resolve(false);
            };

            if (this.videoAd != null) {
                this.videoAd.load().then(() => this.videoAd.show().catch(err => {
                    this.videoAd.load().then(() => {
                        return this.videoAd.show();
                    });
                }));

                // 监听视频播放状态
                OnFire.getInstance().once(EventName.PLAY_VIDEO_STATUS, res => {
                    if (res.key === true) {
                        resolve({
                            status: true,
                            msg: '播放完成'
                        });
                    } else {
                        resolve({
                            status: false,
                            msg: res
                        });
                    };
                })
            } else {
                this.initVideoAd();
            }
        })
    }

    // 插屏广告.(开发者工具上无法展示，插屏广告只支持安卓的头条客户端)
    // Constants.SdkFactory.interstitialAd().then(res => {});
    interstitialAd(callback) {
        if (window.tt) {
            const phoneSystem = tt.getSystemInfoSync().platform === "android";
            // const isToutiaio = tt.getSystemInfoSync().appName === "Toutiao";

            printLog('插屏广告实例', this._interstitialAd);

            if (!phoneSystem) {
                callback(true);
                return;
            }

            this._interstitialAd = tt.createInterstitialAd({
                adUnitId: this.interstitialAdID
            });

            this._interstitialAd.load().then((res) => {
                printLog('展示插屏');
                this._interstitialAd.show().catch(err => {
                    printLog('插屏广告异常1:', this.errHandle[err.errCode]);
                    callback(true);
                });
            }).catch(err => {
                printLog('插屏广告异常2:', this.errHandle[err.errCode]);
                callback(true);
            })

            this._interstitialAd.onLoad(() => {
                printLog('插屏广告加载完成');
            })

            this._interstitialAd.onClose(() => {
                this._interstitialAd.destroy();
                this._interstitialAd.offLoad(() => { });
                this._interstitialAd.offClose(() => { });
                this._interstitialAd.onError(() => { });
                this._interstitialAd = null;
                callback(true);
            })

            this._interstitialAd.onError((err) => {
                printLog('插屏广告异常3:', this.errHandle[err.errCode]);
                this._interstitialAd.destroy();
                this._interstitialAd.offLoad(() => { });
                this._interstitialAd.offClose(() => { });
                this._interstitialAd.onError(() => { });
                this._interstitialAd = null;
                callback(true);
            });

            // if (isToutiaio && phoneSystem) {
            //     printLog('插屏广告实例', this._interstitialAd);

            //     this._interstitialAd = tt.createInterstitialAd({
            //         adUnitId: this.interstitialAdID
            //     });

            //     this._interstitialAd.load().then((res) => {
            //         printLog('展示插屏');
            //         this._interstitialAd.show().catch(err => {
            //             printLog('插屏广告异常1:', this.errHandle[err.errCode]);
            //             callback(true);
            //         });
            //     }).catch(err => {
            //         printLog('插屏广告异常2:', this.errHandle[err.errCode]);
            //         callback(true);
            //     })

            //     this._interstitialAd.onLoad(() => {
            //         printLog('插屏广告加载完成');
            //     })

            //     this._interstitialAd.onClose(() => {
            //         this._interstitialAd.destroy();
            //         this._interstitialAd.offLoad(() => { });
            //         this._interstitialAd.offClose(() => { });
            //         this._interstitialAd.onError(() => { });
            //         this._interstitialAd = null;
            //         callback(true);
            //     })

            //     this._interstitialAd.onError((err) => {
            //         printLog('插屏广告异常3:', this.errHandle[err.errCode]);
            //         this._interstitialAd.destroy();
            //         this._interstitialAd.offLoad(() => { });
            //         this._interstitialAd.offClose(() => { });
            //         this._interstitialAd.onError(() => { });
            //         this._interstitialAd = null;
            //         callback(true);
            //     });
            // } else {
            //     callback(true);
            // }
        }
    }

    // 微信登录
    login() {
        // 当发现之前的数据没有上传时，使用本地数据
        return new Promise<any>((resolve, reject) => {
            printLog('TT登录');
            tt.login({
                force: false,
                success: (res) => {
                    printLog('code:', res.code || res.anonymousCode);
                    API.getInstance().login({ code: res.code || res.anonymousCode, type: res.code ? 0 : 1 }).then(_res => {
                        printLog('获取后端返回的用户信息：', _res);
                        if (_res.status) {
                            resolve({
                                status: true,
                                data: _res.data
                            })
                        } else {
                            resolve({
                                status: false,
                                data: _res.data
                            })
                        }
                    })
                },
                fail: (err) => {
                    resolve({
                        status: false,
                        data: '登录异常: ' + err
                    })
                }
            });
        })
    }

    // 获取用户信息
    getUserInfo(open_id) {
        tt.getSetting({
            success(res) {
                if (res.authSetting['scope.userInfo']) {
                    tt.getUserInfo({
                        success: (data) => {
                            API.getInstance().saveUserInfo({
                                open_id: open_id,
                                avatar_url: data.province,
                                nickname: data.nickName
                            })
                        }
                    });
                }
            }
        });
    }

    // 上传数据到云托管，用于排行榜
    // value = {"keyname": "valuedata"} 或 value = {"keyname_1": { "keyname_1_1": "valuedata_1_1"}, "keyname_2": "value_2"}
    setUserCloudStorage(key, value) {
        if (window.tt) {
            tt.setUserCloudStorage({
                KVDataList: [{
                    key: key,
                    value: JSON.stringify(value)
                }],
                success: (res) => {
                    printLog('托管数据成功', res)
                },
                fail: (err) => {
                    printLog('托管数据失败', err)
                }
            })
        }
    }

    // 长震动
    vibrateLong() {
        if (window.tt) {
            tt.vibrateLong()
        }
    }

    // 短震动
    vibrateShort() {
        if (window.tt) {
            tt.vibrateShort()
        }
    }

    //开始录屏
    StartRecordScreen() {
        if (window.tt) {
            var self = this
            if (this.m_recordManager == null) {
                this.m_recordManager = tt.getGameRecorderManager();
            }
            this.m_recordManager.onStart((res) => {
                console.log("监听录屏开始事件", res);
                this.m_startVideoTime = new Date().getTime();
                this.m_isClipVideo = false;
            })

            this.m_recordManager.onStop((res) => {
                console.log("监听录屏结束事件", res);
                this.m_videoPath = res.videoPath;
                if (this.m_isClipVideo) {
                    this.m_recordManager.clipVideo({
                        path: this.m_videoPath,
                        timeRange: [20, 0],
                        success(res) {
                            console.log('停止事件成功', res);
                            self.m_videoPath = res.videoPath;
                        },
                        fail(e) {
                            console.error(e);
                        }
                    });
                }
            })

            this.m_recordManager.onError(errMsg => {
                console.log("监听录屏错误事件: ", errMsg);
            })

            this.m_recordManager.start({ duration: 300 });
        }
    }

    // 停止录屏
    StopRecordScreen() {
        if (window.tt) {
            let curTime = new Date().getTime();
            let videoTime = Math.floor((curTime - this.m_startVideoTime) / 1000);  //录屏时长

            console.log("录屏时长 = ", videoTime);
            this.m_videoPath = null;

            if (videoTime < 300) {
                if (videoTime < 15) {
                    // 小于15秒不分享
                    this.m_openShareVideo = false;
                    this.m_recordManager.stop();
                    // callback();
                }
                else if (videoTime < 20) {
                    this.m_openShareVideo = true;
                    this.m_recordManager.stop();
                }
                else {
                    // 录屏时间 20 ~ 300
                    this.m_openShareVideo = true;
                    this.m_isClipVideo = true;
                    this.m_recordManager.stop();
                }
            }
            else {
                // 无效录屏
                this.m_openShareVideo = false;
                // callback();
            }
        }
    }

    // 分享录屏
    ShareRecordScreen() {
        // if (this.shareState) return;
        // this.shareState = true;
        return new Promise<any>((resolve, reject) => {
            if (window.tt) {
                if (this.m_videoPath) {
                    tt.shareAppMessage({
                        channel: "video",
                        extra: {
                            videoPath: this.m_videoPath,
                            videoTopics: ['画一画就捣蛋', '抖音小游戏', '画线小游戏']
                        },
                        success(res) {
                            // this.shareState = false;
                            console.log("分享成功", res);
                            resolve(true);
                        },
                        fail(e) {
                            console.log("分享失败", e);
                            // this.shareState = false;
                            OnFire.getInstance().emit(EventName.ADD_MESSAGE, {
                                key: 'TipsMessage',
                                value: { path: 'true', text: '分享失败,请再试' }
                            });
                            resolve(false);
                        }
                    });
                } else {
                    // this.shareState = false;
                    OnFire.getInstance().emit(EventName.ADD_MESSAGE, {
                        key: 'TipsMessage',
                        value: { path: 'true', text: '录屏时间过短无法生成视频,请再试' }
                    });
                    resolve(false);
                }

            } else {
                // this.shareState = false;
                resolve(false);
            }

        });
    }

    //获取屏幕截图
    getScreenShot(rect: Rect, callback?: (spriteframe: SpriteFrame) => void) {
        this.m_screenShot = null;
        this.toTempFilePath(rect, res => {
            let endCallback = (imagePara) => {
                let texture = new cc.Texture2D();
                texture.initWithElement(imagePara);
                this.m_screenShot = new cc.SpriteFrame(texture);

                if (callback) {
                    // 生成的临时文件路径
                    callback(this.m_screenShot);
                }
            }

            let image = new Image(); //创建一个Image对象，实现图片的预下载
            image.src = res.tempFilePath;
            if (image.complete) { // 如果图片已经存在于浏览器缓存，直接调用回调函数
                endCallback(image);
                return; // 直接返回，不用再处理onload事件
            }
            image.onload = () => { //图片下载完毕时异步调用callback函数。
                endCallback(image);
            };
        })
    }

    //显示屏幕截图
    showScreenShot() {
        if (this.m_screenShot != null) {
            return this.m_screenShot;
        } else {
            printLog("没有截图");
            return;
        }
    }
    // showScreenShot(sprite: SpriteComponent | Node) {
    //     if (this.m_screenShot != null) {
    //         if (sprite instanceof cc.Sprite) {
    //             sprite.spriteFrame = this.m_screenShot;
    //         } else if (sprite instanceof cc.Node) {
    //             let Psprite = sprite.getComponent(cc.Sprite) || sprite.addComponent(cc.Sprite);
    //             Psprite.spriteFrame = this.m_screenShot;
    //         }
    //     } else {
    //         console.log("没有截图，请先调用  Utils.getScreenShot 获取截图");
    //     }
    // }

    //截图
    toTempFilePath(rect: Rect, fun: (res: any) => void) {
        if (canvas.toTempFilePath) {
            rect.x = canvas.width * (rect.x / cc.winSize.width);
            rect.y = canvas.height * (rect.y / cc.winSize.height);
            rect.width = canvas.width * (rect.width / cc.winSize.width);
            rect.height = canvas.height * (rect.height / cc.winSize.height);

            canvas.toTempFilePath({
                x: rect.x,
                y: rect.y,
                width: rect.width,
                height: rect.height,
                destWidth: rect.width,
                destHeight: rect.height,
                success: res => {
                    fun(res);
                }
            });

            // canvas.toTempFilePath({
            //     x: 20,
            //     y: 20,
            //     width: 200,
            //     height: 150,
            //     destWidth: 400,
            //     destHeight: 300,
            //     success: (res) => {
            //         fun(res);
            //     },
            // });
        }
    }
}
